//==============================================================================
#include "ClientSocket.h"

using namespace net;
//==============================================================================
ClientSocket::ClientSocket(void)
{
}
//------------------------------------------------------------------------------
ClientSocket::ClientSocket(SOCKET socket)
{
	setSocketConnection(socket);
}
//------------------------------------------------------------------------------
ClientSocket::ClientSocket(string serverHost, string serverPort)
{
	WSADATA wsaData;
    int startUpResult = WSAStartup(MAKEWORD(WSA_VERSION, WSA_REVISION), &wsaData);
    if (startUpResult != 0 ||
		(LOBYTE(wsaData.wVersion) != WSA_VERSION || HIBYTE(wsaData.wVersion) != WSA_REVISION))
    {
        //cout << "WSAStartup failed with error: " << iResult << endl;
    }

	obtainedAddress = NULL;
    memset(&requestedAddress, 0, sizeof(requestedAddress));
    requestedAddress.ai_family = AF_UNSPEC;
    requestedAddress.ai_socktype = SOCK_STREAM;
    requestedAddress.ai_protocol = IPPROTO_TCP;

    int addressResult = getaddrinfo(serverHost.c_str(), serverPort.c_str(), &requestedAddress, &obtainedAddress);
    if (addressResult != 0)
    {
        //cout << "getaddrinfo failed with error: " << iResult << endl;
    }
	socketConnection = INVALID_SOCKET;
}
//------------------------------------------------------------------------------
ClientSocket::~ClientSocket(void)
{
	//WSACleanup();
}
//------------------------------------------------------------------------------
void ClientSocket::doConnect(void) throw (NetworkException)
{
	socketConnection = INVALID_SOCKET;
	struct addrinfo* ptr = NULL;
	int iResult = 0;
	int retries = 10;
	int retry = 1;
	for (ptr=obtainedAddress; ptr!=NULL || retry < retries ; ptr=ptr->ai_next)
    {
        socketConnection = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (socketConnection == INVALID_SOCKET)
        {
			Log::getInstance()->error("[SOCKET] socket() failed! ; (ErrorCode: " + Log::getInstance()->intToString(WSAGetLastError()) + " )");
        }
        iResult = connect(socketConnection, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR)
        {
			Log::getInstance()->error("[SOCKET] connect() failed! ; (ErrorCode: " + Log::getInstance()->intToString(WSAGetLastError()) + " )");
			closesocket(socketConnection);
            socketConnection = INVALID_SOCKET;
			retry++;
			Log::getInstance()->info("[SOCKET] Retrying... " +  Log::getInstance()->intToString(retry));
            continue;
        }
        break;
    }
	if (socketConnection == INVALID_SOCKET)
	{
		string errMessage = "The address information retrieved by function getaddrinfo is invalid.";
		Log::getInstance()->error("[SOCKET] " + errMessage);
		throw NetworkException(errMessage);
	}
	freeaddrinfo(obtainedAddress);
}
